﻿using PrinterMonitorSvc.Common;
using PrinterMonitorSvc.Controller;
using PrinterMonitorSvc.Core.Attribute;
using PrinterMonitorSvc.Core.Enum;
using PrinterMonitorSvc.Ext;
using PrinterMonitorSvc.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PrinterMonitorSvc.Core
{
    /// <summary>
    /// 监控上下文
    /// </summary>
    public class MonitorContext
    {
        #region 属性
        /// <summary>
        /// 打印队列
        /// </summary>
        public static ConcurrentQueue<List<PrintTaskModel>> PrintQueue = new ConcurrentQueue<List<PrintTaskModel>>();
        /// <summary>
        /// 日志队列
        /// </summary>
        public static ConcurrentQueue<KeyValuePair<LogLevelEnum, string>> LogQueue = new ConcurrentQueue<KeyValuePair<LogLevelEnum, string>>();
        /// <summary>
        /// 监听URL集合
        /// </summary>
        private static List<string> _listenerUrl = new List<string>();

        /// <summary>
        /// 处理器字典
        /// </summary>
        private static Dictionary<string, Type> _handlerDict = new Dictionary<string, Type>();

        /// <summary>
        /// 特性字典
        /// </summary>
        private static Dictionary<string, Type> _attributeDict = new Dictionary<string, Type>();

        /// <summary>
        /// 应用路径
        /// </summary>
        private static string contextPath = "/api/";

        /// <summary>
        /// 是否启用性能监控日志
        /// </summary>
        private static bool _IsMonitor = true;

        #endregion

        public static void Init()
        {
            Prepare();
            RegisterAttribute();
            RegisterController();
            RegisterListenerUrl();
            StartListenerTask();
            StartPrintTask();
            StartLogTask();
        }


        #region 准备工作
        /// <summary>
        /// 准备工作
        /// </summary>
        private static void Prepare()
        {
            //创建桌面图标
            SystemHelper.CreateDesktopShortcut();
            //清理过期日志
            SystemHelper.ClearOverdueLog();
            //清理过期PDF
            SystemHelper.ClearOverduePdf();
        }
        #endregion

        #region 注册特性
        /// <summary>
        /// 注册特性
        /// </summary>
        private static void RegisterAttribute()
        {
            _attributeDict.Add("get", typeof(GetMappingAttribute));
            _attributeDict.Add("post", typeof(PostMappingAttribute));
        }
        #endregion

        #region 注册控制器
        /// <summary>
        /// 注册控制器
        /// </summary>
        private static void RegisterController()
        {
            var controllerBase = typeof(ControllerBase);
            var requestMapping = typeof(RequestMappingAttribute);
            var registerTypeList = Assembly.GetExecutingAssembly().GetTypes().Where(s => controllerBase.IsAssignableFrom(s) && controllerBase != s).ToList();
            foreach (var type in registerTypeList)
            {
                var attribute = type.GetCustomAttribute(requestMapping);
                if (null != attribute)
                {
                    var requestMappingAttribute = (RequestMappingAttribute)attribute;
                    string url = contextPath + requestMappingAttribute.Url.Replace("/", string.Empty).ToLower().Trim();
                    _handlerDict.Add(url, type);
                }
            }
        }
        #endregion

        #region 注册监听地址
        /// <summary>
        /// 注册监听地址
        /// </summary>
        private static void RegisterListenerUrl()
        {
            _listenerUrl.Add("http://127.0.0.1:6789");
            _listenerUrl.Add("http://localhost:6789");
            var localIps = NetHelper.GetLanIps();
            if (!localIps.IsListEmpty())
            {
                localIps.ForEach(s =>
                {
                    _listenerUrl.Add($"http://{s}:6789");
                });
            }
        }
        #endregion

        #region 启动监听任务
        /// <summary>
        /// 启动监听任务
        /// </summary>

        private static void StartListenerTask()
        {
            TaskHelper.StartLongTask(() =>
            {
                try
                {
                    NetHelper.StartHttpListener(_listenerUrl, (request, response) =>
                    {
                        TransferRequest(request, response);
                    });
                }
                catch (Exception ex)
                {
                    if (ex is AggregateException)
                    {
                        ex = ex.GetBaseException()?.InnerException;
                    }
                    LogQueue.Enqueue(new KeyValuePair<LogLevelEnum, string>(LogLevelEnum.Error, $"启动监听任务异常：{ex}"));
                }
            });
        }
        #endregion

        #region 启动打印任务
        /// <summary>
        /// 启动打印任务
        /// </summary>

        private static void StartPrintTask()
        {
            TaskHelper.StartLongTask(() =>
            {
                while (true)
                {
                    if (PrintQueue.TryDequeue(out List<PrintTaskModel> tasks))
                    {
                        var time = WatchHelper.Watch(() =>
                        {
                            foreach (var taskGroup in tasks.GroupBy(s => s.PrinterName))
                            {
                                var printName = taskGroup.FirstOrDefault().PrinterName;
                                foreach (var task in taskGroup)
                                {
                                    try
                                    {
                                        for (int i = 0; i < task.PrintCount; i++)
                                        {
                                            PrinterHelper.Print(task.Pdfurl, printName, 100);
                                        }

                                    }
                                    catch (Exception ex)
                                    {
                                        MonitorContext.LogError(ex.ToString());
                                    }
                                }
                            }
                        });
                        if (_IsMonitor)
                        {
                            LogInfo($"请求ID：{tasks.FirstOrDefault().Id}  --  任务数量:{tasks.Sum(s => s.PrintCount)}  --  添加打印机队列总耗时：{time}MS");
                        }
                    }
                    Thread.Sleep(10);
                }
            });
        }
        #endregion

        #region 启动记录日志任务
        /// <summary>
        /// 启动记录日志任务
        /// </summary>

        private static void StartLogTask()
        {
            TaskHelper.StartLongTask(() =>
            {
                while (true)
                {
                    if (LogQueue.TryDequeue(out KeyValuePair<LogLevelEnum, string> logDict))
                    {
                        var key = logDict.Key;
                        var value = logDict.Value;
                        switch (key)
                        {
                            case LogLevelEnum.Info:
                                if (_IsMonitor)
                                {
                                    LogHelper.LogPerformance(value);
                                }
                                break;

                            case LogLevelEnum.Error:
                                LogHelper.LogError(value);
                                MessageBox.Show($"Error=>{value}", SystemConstant.APP_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
                                break;

                            default:
                                break;
                        }
                    }
                    Thread.Sleep(100);
                }
            });
        }
        #endregion

        #region 请求转发
        /// <summary>
        /// 请求转发
        /// </summary>
        /// <param name="request">请求</param>
        /// <param name="response">响应</param>
        private static void TransferRequest(HttpListenerRequest request, HttpListenerResponse response)
        {
            try
            {
                //请求URL
                var action = request.Url.LocalPath.ToLower();
                //请求方式
                var method = request.HttpMethod.ToLower();

                var handler = _handlerDict.FirstOrDefault(s => action == s.Key);
                if (default(KeyValuePair<string, Type>).Equals(handler))
                {
                    ResponseFail(response, $"请求处理器【{action}】未注册");
                    return;
                }
                var handlerType = handler.Value;
                _attributeDict.TryGetValue(method, out Type attributeType);
                var methodObj = handlerType.GetMethods().FirstOrDefault(s => System.Attribute.IsDefined(s, attributeType));
                if (null == methodObj)
                {
                    ResponseFail(response, $"请求处理器【{action}】的【{method}】方法未注册");
                    return;
                }
                var controller = Activator.CreateInstance(handlerType, new object[] { request, response });
                var result = methodObj.Invoke(controller, null);
                ResponseSuccess(response, result);
            }
            catch (Exception ex)
            {
                ResponseFail(response, $"请求转发异常：【{ex}】");
            }
        }
        #endregion

        #region 响应

        /// <summary>
        /// 添加响应头
        /// </summary>
        private static void AddResponseHeaders(HttpListenerResponse response)
        {
            response.AddHeader("Access-Control-Allow-Origin", "*");
            response.AddHeader("Access-Control-Allow-Methods", "*");
            response.AddHeader("Access-Control-Allow-Headers", "*");
        }

        /// <summary>
        /// 响应失败
        /// </summary>
        /// <param name="stream">响应流</param>
        /// <param name="ex">异常原因</param>
        private static void ResponseFail(HttpListenerResponse response, string ex)
        {
            AddResponseHeaders(response);
            JavaResponseModel<string> result = new JavaResponseModel<string>();
            result.errorInfos = new List<ErrorInfo>() { new ErrorInfo() { code = 500, msg = ex } };
            result.success = false;
            var resultByte = Encoding.UTF8.GetBytes(JsonHelper.ConvertJson(result));
            response.OutputStream.Write(resultByte, 0, resultByte.Length);
            response.OutputStream.Close();
        }

        /// <summary>
        /// 响应成功
        /// </summary>
        /// <param name="stream">响应流</param>
        /// <param name="t">响应结果</param>
        private static void ResponseSuccess<T>(HttpListenerResponse response, T t)
        {
            AddResponseHeaders(response);
            JavaResponseModel<T> result = new JavaResponseModel<T>();
            result.success = true;
            result.result = t;
            var resultByte = Encoding.UTF8.GetBytes(JsonHelper.ConvertJson(result));
            response.OutputStream.Write(resultByte, 0, resultByte.Length);
            response.OutputStream.Close();
        }

        #endregion

        #region 日志
        /// <summary>
        /// 记录INFO日志
        /// </summary>
        /// <param name="msg"></param>
        public static void LogInfo(string msg)
        {
            LogQueue.Enqueue(new KeyValuePair<LogLevelEnum, string>(LogLevelEnum.Info, msg));
        }

        /// <summary>
        /// 记录ERROR日志
        /// </summary>
        /// <param name="msg"></param>
        public static void LogError(string msg)
        {
            LogQueue.Enqueue(new KeyValuePair<LogLevelEnum, string>(LogLevelEnum.Error, msg));
        }
        #endregion

    }
}
